from sqlalchemy.orm import Session
from sqlalchemy import or_
from typing import List, Optional, Dict, Any
import uuid
from datetime import datetime

from app.models.graph import Node, Relation, Property
from app.schemas.graph import NodeCreate, NodeUpdate, RelationCreate, RelationUpdate, PropertyCreate

def create_node(db: Session, node_in: NodeCreate) -> Node:
    """创建节点"""
    node_id = str(uuid.uuid4())
    db_node = Node(
        id=node_id,
        type=node_in.type,
        name=node_in.name,
        description=node_in.description,
        metadata=node_in.metadata
    )
    db.add(db_node)

    # 创建属性
    if node_in.properties:
        for prop in node_in.properties:
            db_property = Property(
                id=str(uuid.uuid4()),
                node_id=node_id,
                key=prop.key,
                value=prop.value,
                type=prop.type
            )
            db.add(db_property)

    db.commit()
    db.refresh(db_node)
    return db_node

def get_node(db: Session, node_id: str) -> Optional[Node]:
    """获取节点"""
    return db.query(Node).filter(Node.id == node_id).first()

def update_node(db: Session, node_id: str, node_in: NodeUpdate) -> Optional[Node]:
    """更新节点"""
    db_node = get_node(db, node_id)
    if not db_node:
        return None

    update_data = node_in.dict(exclude_unset=True)
    
    # 更新节点属性
    if "properties" in update_data:
        properties = update_data.pop("properties")
        # 删除现有属性
        db.query(Property).filter(Property.node_id == node_id).delete()
        # 创建新属性
        for prop in properties:
            db_property = Property(
                id=str(uuid.uuid4()),
                node_id=node_id,
                key=prop.key,
                value=prop.value,
                type=prop.type
            )
            db.add(db_property)

    # 更新节点其他字段
    for field, value in update_data.items():
        setattr(db_node, field, value)
    
    db_node.update_time = datetime.utcnow()
    db.commit()
    db.refresh(db_node)
    return db_node

def delete_node(db: Session, node_id: str) -> bool:
    """删除节点"""
    db_node = get_node(db, node_id)
    if not db_node:
        return False
    
    # 删除相关的属性和关系
    db.query(Property).filter(Property.node_id == node_id).delete()
    db.query(Relation).filter(
        or_(Relation.source_id == node_id, Relation.target_id == node_id)
    ).delete()
    
    db.delete(db_node)
    db.commit()
    return True

def create_relation(db: Session, relation_in: RelationCreate) -> Relation:
    """创建关系"""
    db_relation = Relation(
        id=str(uuid.uuid4()),
        **relation_in.dict()
    )
    db.add(db_relation)
    db.commit()
    db.refresh(db_relation)
    return db_relation

def get_relation(db: Session, relation_id: str) -> Optional[Relation]:
    """获取关系"""
    return db.query(Relation).filter(Relation.id == relation_id).first()

def update_relation(db: Session, relation_id: str, relation_in: RelationUpdate) -> Optional[Relation]:
    """更新关系"""
    db_relation = get_relation(db, relation_id)
    if not db_relation:
        return None

    update_data = relation_in.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_relation, field, value)
    
    db_relation.update_time = datetime.utcnow()
    db.commit()
    db.refresh(db_relation)
    return db_relation

def delete_relation(db: Session, relation_id: str) -> bool:
    """删除关系"""
    db_relation = get_relation(db, relation_id)
    if not db_relation:
        return False
    
    db.delete(db_relation)
    db.commit()
    return True

def search_nodes(
    db: Session,
    keyword: str,
    node_type: Optional[str] = None,
    skip: int = 0,
    limit: int = 20
) -> tuple[List[Node], int]:
    """搜索节点"""
    query = db.query(Node)
    
    # 添加搜索条件
    if keyword:
        query = query.filter(
            or_(
                Node.name.ilike(f"%{keyword}%"),
                Node.description.ilike(f"%{keyword}%")
            )
        )
    
    if node_type:
        query = query.filter(Node.type == node_type)
    
    total = query.count()
    nodes = query.offset(skip).limit(limit).all()
    
    return nodes, total

def get_node_relations(
    db: Session,
    node_id: str,
    skip: int = 0,
    limit: int = 20
) -> tuple[List[Relation], int]:
    """获取节点的关系"""
    query = db.query(Relation).filter(
        or_(
            Relation.source_id == node_id,
            Relation.target_id == node_id
        )
    )
    
    total = query.count()
    relations = query.offset(skip).limit(limit).all()
    
    return relations, total 